/*******************************************************************************
 * Copyright (c) 2009 Dop Sun.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     Dop Sun - initial API and implementation
 ******************************************************************************/
package com.softao.ming.gde.internal.ui.launcher;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.variables.IStringVariableManager;
import org.eclipse.core.variables.VariablesPlugin;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.ui.StringVariableSelectionDialog;
import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
import org.eclipse.jface.window.Window;
import org.eclipse.pde.ui.launcher.IPDELauncherConstants;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.DirectoryDialog;
import org.eclipse.swt.widgets.Link;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.dialogs.ContainerSelectionDialog;

import com.softao.ming.gde.internal.ui.block.LocationTextBlock;
import com.softao.ming.gde.internal.ui.util.SWTUtil;

/**
 * Defines the features for the workspace.
 */
public class WorkspaceDataBlock extends AbstractGroupBlock {
	class Listener extends SelectionAdapter implements ModifyListener {
		public void widgetSelected(SelectionEvent e) {
			Object source = e.getSource();
			if (source == mFileSystemButton) {
				handleBrowseFileSystem();
			} else if (source == mWorkspaceButton) {
				handleBrowseWorkspace();
			} else if (source == mVariablesButton) {
				handleInsertVariable();
			} else {
				getTab().updateLaunchConfigurationDialog();
			}
		}

		public void modifyText(ModifyEvent e) {
			getTab().updateLaunchConfigurationDialog();
		}
	}

	private Button mVariablesButton;
	private Button mFileSystemButton;
	private Button mWorkspaceButton;
	private Text mLocationText;
	private Link mLocationLink;
	private Button mClearWorkspaceCheck;
	private Button mAskClearCheck;
	private Button mClearWorkspaceRadio;
	private Button mClearWorkspaceLogRadio;
	private Listener mListener = new Listener();
	private LocationTextBlock mConfigurationLocation;
	
	/**
	 * @param tab
	 */
	public WorkspaceDataBlock(GwtLaunchTab tab) {
		super(tab);
	}
	
	/**
	 * @param parent
	 */
	public void createContent(Composite parent) {
		GridLayout layout = new GridLayout();
		layout.numColumns = 2;
		parent.setLayout(layout);
		parent.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		
		createLocationLinkAndText(parent);
		
		createButtons(parent);
		
		GridData gridData = new GridData();
		gridData.horizontalSpan = 2;
		Composite configurationContainer = new Composite(parent, SWT.NONE);
		configurationContainer.setLayoutData(gridData);
		configurationContainer.setLayout(new GridLayout());
		mConfigurationLocation = new LocationTextBlock();
		mConfigurationLocation.createControl(configurationContainer);
		mConfigurationLocation.setLabel("Configuration Location:");
		mConfigurationLocation.addModifyListener(mListener);
	}

	/**
	 * @param parent
	 */
	private void createButtons(Composite parent) {
		GridLayout layout;
		Composite buttons = new Composite(parent, SWT.NONE);
		layout = new GridLayout(7, false);
		layout.marginHeight = layout.marginWidth = 0;
		buttons.setLayout(layout);
		GridData gd = new GridData(GridData.FILL_HORIZONTAL);
		gd.horizontalSpan = 2;
		buttons.setLayoutData(gd);
		
		mClearWorkspaceCheck = new Button(buttons, SWT.CHECK);
		mClearWorkspaceCheck.setText("&Clear:");
		mClearWorkspaceCheck.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING));
		mClearWorkspaceCheck.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				mAskClearCheck.setEnabled(mClearWorkspaceCheck.getSelection());
				mClearWorkspaceRadio.setEnabled(mClearWorkspaceCheck.getSelection());
				mClearWorkspaceLogRadio.setEnabled(mClearWorkspaceCheck.getSelection());
				getTab().updateLaunchConfigurationDialog();
			}
		});

		mClearWorkspaceRadio = new Button(buttons, SWT.RADIO);
		mClearWorkspaceRadio.setText("&workspace");
		mClearWorkspaceRadio.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING));
		mClearWorkspaceRadio.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				getTab().updateLaunchConfigurationDialog();
			}
		});
		mClearWorkspaceLogRadio = new Button(buttons, SWT.RADIO);
		mClearWorkspaceLogRadio.setText("log o&nly");
		mClearWorkspaceLogRadio.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		mClearWorkspaceLogRadio.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				getTab().updateLaunchConfigurationDialog();
			}
		});
		
		mWorkspaceButton = createPushButton(buttons, "&Workspace...");
		mFileSystemButton = createPushButton(buttons, "&File System...");
		mVariablesButton = createPushButton(buttons, "Varia&bles...");
		
		mAskClearCheck = new Button(parent, SWT.CHECK);
		mAskClearCheck.setText("Ask &for confirmation before clearing");
		gd = new GridData();
		gd.horizontalSpan = 2;
		mAskClearCheck.setLayoutData(gd);
		mAskClearCheck.addSelectionListener(mListener);
	}

	private Button createPushButton(Composite parent, String text) {
		Button button = new Button(parent, SWT.PUSH);
		button.setText(text);
		button.setLayoutData(new GridData());
		button.addSelectionListener(mListener);
		SWTUtil.setButtonDimensionHint(button);
		return button;
	}
	
	@Override
	protected String getText() {
		return "Workspace Data";
	}
	
	private void createLocationLinkAndText(Composite parent) {
		mLocationLink = new Link(parent, SWT.NONE);
		mLocationLink.setText("<a>" + "Location:" + "</a>");
		
		mLocationText = new Text(parent, SWT.SINGLE | SWT.BORDER);
		GridData gd = new GridData(GridData.FILL_HORIZONTAL);
		gd.widthHint = 400;
		mLocationText.setLayoutData(gd);
	}
	
	private void handleBrowseFileSystem() {
		DirectoryDialog dialog = new DirectoryDialog(getTab().getControl().getShell());
		dialog.setFilterPath(getLocation());
		dialog.setText("Directory Selection");
		dialog.setMessage("Choose a directory:");
		String result = dialog.open();
		if (result != null)
			mLocationText.setText(result);
	}

	private void handleBrowseWorkspace() {
		ContainerSelectionDialog dialog = new ContainerSelectionDialog(getTab().getControl().getShell(), getContainer(), true, "Choose a location relative to the workspace:");
		if (dialog.open() == Window.OK) {
			Object[] result = dialog.getResult();
			if (result.length == 0)
				return;
			IPath path = (IPath) result[0];
			mLocationText.setText("${workspace_loc:" + path.makeRelative().toString() + "}"); //$NON-NLS-1$ //$NON-NLS-2$
		}
	}
	
	private IContainer getContainer() {
		String path = getLocation();
		if (path.length() > 0) {
			IResource res = null;
			IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
			if (path.startsWith("${workspace_loc:")) { //$NON-NLS-1$
				IStringVariableManager manager = VariablesPlugin.getDefault().getStringVariableManager();
				try {
					path = manager.performStringSubstitution(path, false);
					IContainer[] containers = root.findContainersForLocation(new Path(path));
					if (containers.length > 0)
						res = containers[0];
				} catch (CoreException e) {
				}
			} else {
				res = root.findMember(path);
			}
			if (res instanceof IContainer) {
				return (IContainer) res;
			}
		}
		return ResourcesPlugin.getWorkspace().getRoot();
	}

	private String getLocation() {
		return mLocationText.getText().trim();
	}

	private void handleInsertVariable() {
		StringVariableSelectionDialog dialog = new StringVariableSelectionDialog(getTab().getControl().getShell());
		if (dialog.open() == Window.OK)
			mLocationText.insert(dialog.getVariableExpression());
	}

	@Override
	public void performApply(ILaunchConfigurationWorkingCopy configuration) {
		configuration.setAttribute(IJavaLaunchConfigurationConstants.ATTR_WORKING_DIRECTORY, getLocation());
		configuration.setAttribute(IPDELauncherConstants.DOCLEAR, mClearWorkspaceCheck.getSelection());
		configuration.setAttribute(IPDELauncherConstants.ASKCLEAR, mAskClearCheck.getSelection());
		configuration.setAttribute("clearwslog", mClearWorkspaceLogRadio.getSelection());
		configuration.setAttribute("configurationLocation", mConfigurationLocation.getLocation());
	}
	
	@Override
	public void setDefaults(ILaunchConfigurationWorkingCopy configuration) {
		configuration.setAttribute(IJavaLaunchConfigurationConstants.ATTR_WORKING_DIRECTORY, getDefaultWorkspaceLocation(configuration.getName()));
		configuration.setAttribute(IPDELauncherConstants.DOCLEAR, false);
		configuration.setAttribute(IPDELauncherConstants.ASKCLEAR, true);
		configuration.setAttribute("clearwslog", false);
		configuration.setAttribute("configurationLocation", "");
	}
	
	@Override
	public void initializeFrom(ILaunchConfiguration configuration) throws CoreException {
		mLocationText.setText(configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_WORKING_DIRECTORY, getDefaultWorkspaceLocation(configuration.getName())));
		mClearWorkspaceCheck.setSelection(configuration.getAttribute(IPDELauncherConstants.DOCLEAR, false));
		mAskClearCheck.setSelection(configuration.getAttribute(IPDELauncherConstants.ASKCLEAR, true));
		mAskClearCheck.setEnabled(mClearWorkspaceCheck.getSelection());
		mClearWorkspaceLogRadio.setEnabled(mClearWorkspaceCheck.getSelection());
		mClearWorkspaceLogRadio.setSelection(configuration.getAttribute("clearwslog", false));
		mClearWorkspaceRadio.setEnabled(mClearWorkspaceCheck.getSelection());
		mClearWorkspaceRadio.setSelection(!configuration.getAttribute("clearwslog", false));
		mConfigurationLocation.setLocation(configuration.getAttribute("configurationLocation", ""));
	}
	
	private static String getDefaultWorkspaceLocation(String uniqueName) {
		return "${workspace_loc}/../runtime-" + uniqueName.replaceAll("\\s", ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
	}

}
